﻿namespace MapleRock.P2PEmulator.Core.Events
{
  using System;
  using System.Collections.Generic;
  using System.Diagnostics;
  using System.IO;
  using System.Linq;
  using System.Text;
  using System.Xml.Serialization;

  public enum TranslationAgentType
  {
    Invalid = 0,
    Peer = 1,
    Router = 2,
  }

  public enum TranslationStatus
  {
    Invalid = 0,
    Begin = 1,
    LatencyPassed = 2,
    Success = 3,
    Failure = 4,
  }

  public sealed class TranslationEvent : BaseEvent
  {
    public TranslationEvent(
      uint timestamp,
      uint fromId, 
      TranslationAgentType fromType,
      uint toId,
      TranslationAgentType toType,
      TranslationStatus status)
      : base(EventType.TranslationEvent, timestamp)
    {
      this.FromId = fromId;
      this.FromType = fromType;
      this.ToId = toId;
      this.ToType = toType;
      this.Status = status;
    }

    public uint FromId { get; private set; }

    public TranslationAgentType FromType { get; private set; }

    public uint ToId { get; private set; }

    public TranslationAgentType ToType { get; private set; }

    public TranslationStatus Status { get; private set; }

    public override void Deserialize(BinaryReader input)
    {
      base.Deserialize(input);

      this.FromId = input.ReadUInt32();
      if (0 == this.FromId)
      {
        throw new FormatException("[EVENTS]: FromId must be greater than zero.");
      }

      this.FromType = (TranslationAgentType)input.ReadByte();
      if (TranslationAgentType.Invalid == this.FromType)
      {
        throw new FormatException("[EVENTS]: FromType must be not Invalid.");
      }

      this.ToId = input.ReadUInt32();
      if (0 == this.FromId)
      {
        throw new FormatException("[EVENTS]: FromId must be greater than zero.");
      }

      this.ToType = (TranslationAgentType)input.ReadByte();
      if (TranslationAgentType.Invalid == this.ToType)
      {
        throw new FormatException("[EVENTS]: ToType must be not Invalid.");
      }

      this.Status = (TranslationStatus)input.ReadByte();
      if (TranslationStatus.Invalid == this.Status)
      {
        throw new FormatException("[EVENTS]: Status must be not Invalid.");
      }
    }

    public override void Serialize(BinaryWriter output)
    {
      if (null == output)
      {
        throw new ArgumentNullException("output");
      }

      base.Serialize(output);

      Debug.Assert(this.FromId > 0, "this.FromId > 0");
      output.Write(Convert.ToUInt32(this.FromId));

      Debug.Assert(
        this.FromType != TranslationAgentType.Invalid,
        "this.FromType != TranslationAgentType.Invalid");
      output.Write(Convert.ToByte(this.FromType));

      Debug.Assert(this.ToId > 0, "this.ToId > 0");
      output.Write(Convert.ToUInt32(this.ToId));

      Debug.Assert(
        this.ToType != TranslationAgentType.Invalid,
        "this.ToType != TranslationAgentType.Invalid");
      output.Write(Convert.ToByte(this.ToType));

      Debug.Assert(
        this.Status != TranslationStatus.Invalid,
        "this.Status != TranslationStatus.Invalid");
      output.Write(Convert.ToByte(this.Status));
    }

    public override string ToString()
    {
      var str = string.Format(
        "TranslationEvent;FromId={0};FromType={1};ToId={2};ToType={3};Status={4}",
        this.FromId,
        this.FromType,
        this.ToId,
        this.ToType,
        this.Status);
      return str;
    }
  }
}
